#include "Document.h"



Document::Document (Ptr< QImage > pImage, const QString & imagePath,
					const QString & title) : _imagePath (imagePath), _curLayer (0), 
					_layers (), _isPreviewMode (false), _pIterpolateMethod (), 
					_pAction (NULL)
{
	if (title.isEmpty ())
		_title = _imagePath.mid (_imagePath.lastIndexOf ('/') + 1);
	else
		_title = title;
	_format = pImage->format ();
	addLayer (new Layer (tr ("Background"), new QImage (
		pImage->convertToFormat (QImage::Format_ARGB32))));
	_canvasSize = pImage->size ();
	_pCanvasRegion = new QRect (QPoint (), pImage->size ());
	refreshCompositedImage ();
}



Document::~Document ()
{

}



void Document::resize (const QSize & size)
{
	throw ("to be implemented");
}



void Document::translateAll (const QPoint & vec)
{
	throw ("to be implemented");
}



Ptr< QRect > Document::getCanvasRegion ()
{
	return _pCanvasRegion;
}



const Ptr< QRect > Document::getCanvasRegion () const
{
	return _pCanvasRegion;
}



Ptr< Layer > Document::getLayer (int index)
{
	if (index < 0 || index >= _layers.size ())
		OOPTHROW (OutOfRangeException);
	return _layers[index];
}

const Ptr< Layer > Document::getLayer (int index) const
{
	if (index < 0 || index >= _layers.size ())
		OOPTHROW (OutOfRangeException);
	return _layers[index];
}



Ptr< Layer > Document::getCurrentLayer ()
{
	if (_curLayer < 0 || _curLayer >= _layers.size ())
		OOPTHROW (OutOfRangeException);
	return _layers[_curLayer];
}

const Ptr< Layer > Document::getCurrentLayer () const
{
	if (_curLayer < 0 || _curLayer >= _layers.size ())
		OOPTHROW (OutOfRangeException);
	return _layers[_curLayer];
}



void Document::refreshCompositedImage ()
{
	if (_isPreviewMode)
		throw ("refresh composited image in preview mode");

	QRect region (*_pCanvasRegion);

	_pCompositedImage = new QImage (region.size (), QImage::Format_ARGB32);
	_pCompositedImage->fill (0);

	for (int i = 0; i < _layers.size (); ++i)
	{
		QRect layerRegion (_layers[i]->getRegion ());
		QRect targetRegion = layerRegion & region;
		QRect srcRegion (targetRegion);
		srcRegion.translate (-layerRegion.topLeft ());
		QRgb * a = (QRgb *)_pCompositedImage->scanLine (0);
		QRgb * b = (QRgb *)_layers[i]->getImage ()->scanLine (0);
		_pCompositedImage = _layers[i]->getCompositionOperation ()
				->process (_layers[i]->getImage (), _pCompositedImage,
				srcRegion, _pCompositedImage->rect (), 
				targetRegion.topLeft (), QPoint (), 
				_pCompositedImage->size ());
	}
}



Ptr< QImage > Document::getPreview (QRect region)
{
	if (_isPreviewMode)
		_pTempPreviewImage = _getPreviewImage (region);
	else
		_pTempPreviewImage = new QImage (_pCompositedImage->copy (region));
	return _pTempPreviewImage;
}



Ptr< QImage > Document::getPreview ()
{
	if (_isPreviewMode)
		_pTempPreviewImage = _getPreviewImage (*_pCanvasRegion);
	else
		_pTempPreviewImage = _pCompositedImage;
	return _pTempPreviewImage;
}



void Document::addLayer (Ptr< Layer > pNewLayer)
{
	_layers.push_back (pNewLayer);
	_curLayer = _layers.size () - 1;
	//   connect (pNewLayer, layerModeChanged(), this, refreshMode());
}



Ptr< QImage > Document::_getPreviewImage (QRect region)
{
	_pAction->updatePreview (region);

	Ptr< QImage > pPreview = new QImage (region.size (), QImage::Format_ARGB32);
	pPreview->fill (0);

	for (int i = 0; i < _layers.size (); ++i)
	{
		QRect layerRegion (_layers[i]->getRegion ());
		QRect targetRegion = layerRegion & region;
		QRect srcRegion (targetRegion);
		Ptr< QImage > srcImage;
		if (_layers[i]->isInPreviewMode ())
		{
			srcImage = _layers[i]->getPreviewImage ();
			srcRegion = srcImage->rect ();
		}
		else
		{
			srcImage = _layers[i]->getImage ();
			srcRegion.translate (-layerRegion.topLeft ());
		}
		targetRegion.translate (-region.topLeft ());
		pPreview = _layers[i]->getCompositionOperation ()->process (
				srcImage, pPreview, 
				srcRegion, pPreview->rect (),
				targetRegion.topLeft (), QPoint (),
				pPreview->size ());
	}

	return pPreview;
}

void Document::openPreview (Ptr< AbstractAction > pAction)
{
	_pAction = pAction;
	_isPreviewMode = true;
}

void Document::closePreview ()
{
	_pAction = NULL;
	_isPreviewMode = false;
	for (int i = 0; i < _layers.size (); ++i)
		_layers[i]->closePreview ();
	refreshCompositedImage ();
}

Ptr< QImage > Document::getCompositedImage ()
{
	return _pCompositedImage;
}

int Document::getLayerCount () const
{
	return _layers.size ();
}

void Document::setCurrentLayer (int index)
{
	_curLayer = index;
}

Ptr< QImage > Document::getTempPreview ()
{
	return _pTempPreviewImage;
}



// void Document::refreshMode ()
// {
//   for (int i = 0; i < _layers.size (); ++i)
//   {
//     if (_layers[i]->isInPreviewMode ())
//     {
//       _isPreviewMode = true;
//       return;
//     }
//   }
//   _isPreviewMode = false;
// }
// 
// 
// 
// void Document::refreshInfo ()
// {
//   _clearInfo ();
//   if (_pImage != NULL && !_pImage->isNull ())
//   {
//     _width = _pImage->width ();
//     _height = _pImage->height ();
//     _calcHistogram ();
//   }
//   emit infoChanged ();
// }
// 